package com.pipe.servicepipe.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.pipe.commonutils.ResultCode;
import com.pipe.servicebase.exception.PipeException;
import com.pipe.servicepipe.entity.PipeUser;
import com.pipe.servicepipe.entity.bo.AdminUserDetails;
import com.pipe.servicepipe.mapper.PipeUserMapper;
import com.pipe.servicepipe.service.PipeAdminService;
import com.pipe.servicepipe.util.JwtTokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName PipeAdminServiceImpl
 * @Author HETAO
 * @Date 2020/7/19 17:08
 */
@Service
@Slf4j
public class PipeAdminServiceImpl implements PipeAdminService {

    private static String PRFIX_SMS = "PIPE:PHONE:";

    private static String PRFIX_SMS_COUNT = "PIPE:PHONE:COUNT:";

    @Resource
    private RabbitTemplate rabbitTemplate;

    @Resource
    private PipeUserMapper pipeUserMapper;

    @Resource
    private JwtTokenUtil jwtTokenUtil;

    @Resource
    private PasswordEncoder passwordEncoder;

    @Resource
    private RedisTemplate redisTemplate;

    @Override
    public String login(String username, String password) throws Exception{
        String token = null;
        UserDetails userDetails = loadUserByUsername(username);
        if (!passwordEncoder.matches(password, userDetails.getPassword())) {
            throw new PipeException(ResultCode.ERROR, "密码不正确");
        }
        //
        UsernamePasswordAuthenticationToken authentication =
                new UsernamePasswordAuthenticationToken(userDetails,
                        null,
                        userDetails.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authentication);
        return token;
    }

    @Override
    public UserDetails loadUserByUsername(String username) {
        PipeUser pipeUser = pipeUserMapper.getAdmin(username);
        if (pipeUser != null) {
            //todo 查询权限
            return new AdminUserDetails(pipeUser);
        }
        throw new PipeException(ResultCode.ERROR, "用户名或密码错误");
    }

    public UserDetails loadUserByPhone(String phone) {
        PipeUser pipeUser = pipeUserMapper.getAdminByPhone(phone);
      /*  PipeUser pipeUser = new PipeUser();
        pipeUser.setUserName("root");
        pipeUser.setPassword("password");
        pipeUser.setStatus(3);*/
        if (pipeUser != null) {
            //todo 查询权限
            return new AdminUserDetails(pipeUser);
        }
        throw new PipeException(ResultCode.ERROR, "此号码用户不存在");
    }

    @Override
    public String loginByPhone(String phone,String captcha) {
        Object num = redisTemplate.boundValueOps(PRFIX_SMS + phone).get();
        if (num == null || !captcha.equals(num)) {
            throw new PipeException(ResultCode.ERROR, "验证码有误,请重新输入");
        }
        UserDetails userDetails = this.loadUserByPhone(phone);

        String token = null;
        UsernamePasswordAuthenticationToken authentication =
                new UsernamePasswordAuthenticationToken(userDetails,
                        null,
                        userDetails.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authentication);
        token = jwtTokenUtil.generateToken(userDetails);
        return token;
    }


    @Override
    public void loginBySms(String phone) {
        PipeUser pipeUser = this.pipeUserMapper.getAdminByPhone(phone);
        // if (pipeUser == null) {
        //     throw new PipeException(ResultCode.ERROR,"该号码不是内部号码.无法登录！");
        // }

        String number = RandomUtil.randomNumbers(6);
        Map map = new HashMap<>();
        map.put("phone", phone);
        map.put("number", number);
        BoundValueOperations valueOps = redisTemplate.boundValueOps(PRFIX_SMS + phone);
        BoundValueOperations ops = redisTemplate.boundValueOps(PRFIX_SMS_COUNT + phone);
        Object captcha = ops.get();
        if (captcha != null) {
            Integer count = (Integer)captcha;
            if (count >= 5) {
                String message = String.format("你今日发送短信已有:%d次,请联系何涛解封,", count);
                throw new PipeException(ResultCode.ERROR,message);
            }
        }
        ops.increment(1);
        ops.expire(1, TimeUnit.DAYS);
        valueOps.set(number, 5, TimeUnit.MINUTES);
        //rabbitTemplate.convertAndSend(QueueEnum.QUEUE_ENUM.getRouteKey(), map);
    }

}
